home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
macros
/
latex209
/
contrib
/
trees
/
eppstein
/
trees.sty
< prev
Wrap
Text File
|
1993-11-07
|
7KB
|
121 lines
% treedef.tex
%
% These definitions for tree macros are taken from "Trees in TeX",
% by David Eppstein, as published in TUGboat 6#1, March 1985.
% David Eppstein's address (as of 15 June 1988) is
% Computer Science Department
% Columbia University
% New York, NY 10027
% Eppstein@cs.Columbia.edu
\newbox\treebox
\def\tree{\global\setbox\treebox=\boxtree}
\def\subtree{\ettext \boxtree}
\def\leaf#1{\subtree#1\endsubtree}
\def\endsubtree{\ettext \egroup}
\def\endtree{\endsubtree \settreesizes \typesettree}
\newif\iftreetext\treetextfalse % Whether still aligning text
\def\boxtree{\hbox\bgroup % Start outer box of tree or subtree
\baselineskip 2.5ex % Narrow line spacing slightly
\tabskip 0pt % No spurious glue in alignment
\vbox\bgroup % Start inner text \vbox
\treetexttrue % Remember for \ettext
\let\par\crcr \obeylines % New line breaks without explicit \cr
\halign\bgroup##\hfil\cr} % Start alignment with simple template
\def\ettext{\iftreetext % Are we still in inner text \vbox?
\crcr\egroup \egroup \fi} % Yes, end alignment and box
\def\cons#1#2{\edef#2{\xmark #1#2}} % Add something to start of list.
\def\car#1{\expandafter\docar#1\docar} % Take first element of list
\def\docar\xmark#1\xmark#2\docar{#1} % ..by ignoring rest in expansion.
\def\cdr#1{\expandafter\docdr#1\docdr#1} % Similarly, drop first element.
\def\docdr\xmark#1\xmark#2\docdr#3{\def#3{\xmark #2}}
\def\xmark{\noexpand\xmark} % List separator expands to self.
\def\nil{\xmark} % Empty list is just a separator.
\def\settreesizes{\setbox0=\copy\treebox \global\let\treesizes\nil \setsizes}
\newdimen\treewidth % Width of this part of the tree.
\def\setsizes{\setbox0=\hbox\bgroup % Get a horiz list as a workspace.
\unhbox0\unskip % Take tree, unpack it into horiz list.
\inittreewidth % Get old width at this level.
\sizesubtrees % Recurse through all subtrees.
\sizelevel % Now set width from remaining \vbox.
\egroup} % All done, finish our \hbox.
\def\inittreewidth{\ifx\treesizes\nil % If this is the first at this level
\treewidth=0pt % ..then we have no previous max width.
\else \treewidth=\car\treesizes % Otherwise take old max level width
\global\cdr\treesizes % ..and advance level width storage
\fi} % ..in preparation for next level.
\def\sizesubtrees{\loop % For each box in horiz list (subtree)
\setbox0=\lastbox \unskip % ..pull it off list and flush glue.
\ifhbox0 \setsizes % If hbox, it's a subtree - recurse
\repeat} % ..and loop; end loop on tree text.
\def\sizelevel{\ifdim\treewidth<\wd0 % If greater than previous maximum
\treewidth=\wd0 \fi % Then set max to new high
\global\cons{\the\treewidth}\treesizes}% In either case, put back on list
\newdimen\treeheight % Height of this part of the tree.
\newif\ifleaf % Tree has no subtrees (is a leaf).
\newif\ifbotsub % Bottom subtree of parent.
\newif\iftopsub % Top subtree of parent.
\def\typesettree{\medskip \maketree \medskip} % Make whole tree with spacing.
\def\maketree{\hbox{\treewidth=\car\treesizes % Get width at this level.
\cdr\treesizes % Set up width list for recursion.
\makesubtreebox\unskip % Set \treebox to text, make subtrees.
\ifleaf \makeleaf % No subtrees, add glue.
\else \makeparent \fi}} % Have subtrees, stick them at right.
{\catcode`@=11 % Be able to use \voidb@x.
\gdef\makesubtreebox{\unhbox\treebox % Open up tree or subtree.
\unskip\global\setbox\treebox\lastbox % Pick up very last box.
\ifvbox\treebox % If we're already at the \vbox
\global\leaftrue \let\next\relax % ..then this is a leaf.
\else \botsubtrue % Otherwise, we have subtrees.
\setbox0\box\voidb@x % Init stack of processed subs
\botsubtrue \let\next\makesubtree % ..and call \maketree on them.
\fi \next}} % Finish up for whichever it was.
\def\makesubtree{\setbox1\maketree % Call \maketree on this subtree.
\unskip\global\setbox\treebox\lastbox % Pick up box before it.
\treeheight=\ht1 % Get height of subtree we made
\advance\treeheight 2ex % Add some room around the edges
\ifhbox\treebox \topsubfalse % If picked up box is a \vbox,
\else \topsubtrue \fi % ..this is the top, otherwise not.
\addsubtreebox % Stack subtree with the rest.
\iftopsub \global\leaffalse % If top, remember not a leaf
\let\next\relax \else % ..(after recursion), set return.
\botsubfalse \let\next\makesubtree % Otherwise, we have more subtrees.
\fi \next} % Do tail recursion or return.
\def\addsubtreebox{\setbox0=\vbox{\subtreebox\unvbox0}}
\def\subtreebox{\hbox\bgroup % Start \hbox of tree and lines
\vbox to \treeheight\bgroup % Start \vbox for vertical rules.
\ifbotsub \iftopsub \vfil % If both bottom and top subtree
\hrule width 0.4pt % ..vertical rule is just a dot.
\else \treehalfrule \fi \vfil % Bottom gets half-height rule.
\else \iftopsub \vfil \treehalfrule % Top gets half-height the other way.
\else \hrule width 0.4pt height \treeheight \fi\fi % Middle, full height.
\egroup % Finish vertical rule \vbox.
\treectrbox{\hrule width 1em}\hskip 0.2em\treectrbox{\box1}\egroup}
\def\treectrbox#1{\vbox to \treeheight{\vfil #1\vfil}}
\def\treehalfrule{\dimen0=\treeheight % Get total height.
\divide\dimen0 2\advance\dimen0 0.2pt % Divide by two, add half horiz height.
\hrule width 0.4pt height \dimen0} % Make a vertical rule that high.
\def\makeleaf{\box\treebox} % Add leaf box to horiz list.
\def\makeparent{\ifdim\ht\treebox>\ht0 % If text is higher than subtrees
\treeheight=\ht\treebox % ..use that height.
\else \treeheight=\ht0 \fi % Otherwise use height of subtrees.
\advance\treewidth-\wd\treebox % Take remainder of level width
\advance\treewidth 1em % ..after accounting for text and glue.
\treectrbox{\box\treebox}\hskip 0.2em % Add text, space before connection.
\treectrbox{\hrule width \treewidth}\treectrbox{\box0}} % Add \hrule, subs.
\endinput